package com.compunit.composite.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;

import com.compunit.composite.core.interfaces.IClassExporter;

/**
 * <code>ClassExporter</code> defines the implementation
 * of the class exporting utility unit.
 *
 * @author Yi Wang (Neakor)
 * @version Creation date: 11-12-2009 19:09 EST
 * @version Modified date: 11-22-2009 14:11 EST
 */
public class ClassExporter extends AbstractExporter implements IClassExporter {
	/**
	 * The <code>Map</code> of <code>String</code>
	 * class names to <code>Class</code> objects to
	 * be exported.
	 */
	private final Map<String, Class<?>> classes;

	/**
	 * Constructor of <code>ClassExporter</code>.
	 */
	public ClassExporter() {
		this.classes = new HashMap<String, Class<?>>();
	}

	@Override
	protected void doExport(File destination) throws URISyntaxException, IOException {
		final JarOutputStream output = new JarOutputStream(new FileOutputStream(destination));
		for(final Class<?> c : this.classes.values()) {
			// Link to class file and path.
			final String path = c.getName().replace(".", "/").concat(".class");
			final File classfile = new File(this.getClass().getResource("/"+path).toURI());
			// Add jar entry.
			output.putNextEntry(new JarEntry(path));
			// Write in class bytes.
			final FileInputStream fis = new FileInputStream(classfile);
			int count = 0;
			byte bytes[] = new byte[16384];
			while ((count = fis.read (bytes, 0, bytes.length)) != -1){
				output.write (bytes,0,count);
			}
			fis.close();
		}
		output.close();
	}

	@Override
	public void addClass(final Class<?> classobject) {
		if(classobject == null) return;
		final String classname = classobject.getName();
		if(this.classes.containsKey(classname)) return;
		this.classes.put(classname, classobject);
	}

	@Override
	public void removeClass(final Class<?> classobject) {
		if(classobject == null) return;
		this.classes.remove(classobject.getName());
	}

	@Override
	public boolean containsClass(final Class<?> classobject) {
		if(classobject == null) return false;
		return this.classes.containsKey(classobject.getName());
	}

	@Override
	public void cleanup() {
		this.classes.clear();
	}

	@Override
	public boolean isEmpty() {
		return this.classes.isEmpty();
	}
}
